/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "render/lottie_render.h"
#include "canvas.h"
#include "common/common.h"
#include "native_drawing/drawing_gpu_context.h"
#include "native_drawing/drawing_surface.h"
#include "node/lottie_manager_map.h"
#include <cstdint>
#include <native_buffer/native_buffer.h>

namespace LottiePro {

LottieRender::LottieRender()
{
    lottieRenderLayer_ = std::make_shared<LottieRenderLayer>();
    canvas_ = std::make_shared<drawing::Canvas>();
    gpuContext_ = OH_Drawing_GpuContextCreate();
}

LottieRender::~LottieRender()
{
    if (surface_ != nullptr) {
        OH_Drawing_SurfaceDestroy(surface_);
        surface_ = nullptr;
    }
    if (gpuContext_ != nullptr) {
        OH_Drawing_GpuContextDestroy(gpuContext_);
        gpuContext_ = nullptr;
    }
}

void LottieRender::RenderTree(const std::string xcomponentId, const LOTLayerNode *rootNode,
                              CalculatePosition *calculatePosition)
{
    if (!rootNode || calculatePosition->width <= 0 || calculatePosition->height <= 0) {
        DRAWING_LOGE("Invalid parameters for RenderTree");
        return;
    }
    auto window = LottieManagerMap::getInstance().GetWindowById(xcomponentId);
    if (!window) {
        DRAWING_LOGE("Failed to get window for xcomponentId: %s", xcomponentId.c_str());
        return;
    }
    int32_t width = 0;
    int32_t height = 0;
    lottieRenderLayer_->SetSize(calculatePosition->width, calculatePosition->height);
    LottieManagerMap::getInstance().GetRectById(xcomponentId, width, height);
    if (width == 0 || height == 0) {
        return;
    }
    OH_Drawing_Image_Info imageinfo = {static_cast<int32_t>(width), static_cast<int32_t>(height),
                                       COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_PREMUL};
    surface_ = OH_Drawing_SurfaceCreateOnScreen(gpuContext_, imageinfo, window);
    canvas_ = std::make_shared<drawing::Canvas>(OH_Drawing_SurfaceGetCanvas(surface_));
    this->HandleCanvas(canvas_, calculatePosition);
    // 处理根层节点
    lottieRenderLayer_->RenderLayer(canvas_, rootNode);
    OH_Drawing_SurfaceFlush(surface_);
    OH_Drawing_SurfaceDestroy(surface_);
}

void LottieRender::HandleCanvas(std::shared_ptr<drawing::Canvas> canvas, CalculatePosition *calculatePosition)
{
    if (canvas == nullptr) {
        return;
    }
    size_t a = 0x00;
    size_t r = 0xff;
    size_t g = 0xff;
    size_t b = 0xff;
    // 使用透明清除画布内容
    canvas->Clear(drawing::Color::SetArgb(a, r, g, b));
    // 应用偏移
    if (calculatePosition->x != 0 || calculatePosition->y != 0) {
        canvas->Translate(static_cast<float>(calculatePosition->x), static_cast<float>(calculatePosition->y));
    }
}

} // namespace LottiePro